#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>


#define FILE_NAME "./a.out"

int main(int argc, char const *argv[])
{
    struct stat stFile;
    int iRet;
    iRet = stat( FILE_NAME, &stFile );

    printf("Some visiable stat information of %s\n", FILE_NAME);
    printf( "mode\tnlink\tuid\tgid\tsize\t\n" );
    printf( "%d\t%ld\t%d\t%d\t%ld\t\n",
            stFile.st_mode, stFile.st_nlink, stFile.st_uid, stFile.st_gid, stFile.st_size);

    /* 
    "man 7 inode" could get the "st_mode" detail.
    st_mode contains the file type and mode
    */

   // Judge which file type
    if ( ( stFile.st_mode & S_IFMT ) == S_IFSOCK )
    {
        printf( "&: Socekt File\n" );
    } 

    if ( ( stFile.st_mode & S_IFMT ) == S_IFLNK )
    {
        printf( "&: Symbolic Link\n" );
    }

    if ( ( stFile.st_mode & S_IFMT ) == S_IFREG )
    {
        printf( "&: Regular File\n" );
    }

    if ( ( stFile.st_mode & S_IFMT ) == S_IFBLK )
    {
        printf( "&: Block Device\n" );
    }

    if ( ( stFile.st_mode & S_IFMT ) == S_IFDIR )
    {
        printf( "&: Directory\n" );
    }

    if ( ( stFile.st_mode & S_IFMT ) == S_IFCHR )
    {
        printf( "&: Character Device\n" );
    }

    if ( ( stFile.st_mode & S_IFMT ) == S_IFIFO )
    {
        printf( "&: FIFO\n" );
    }
    
    // Judge which file type by macros defined by POSIX
    if ( S_ISSOCK(stFile.st_mode) )
    {
        printf( "M: Socekt File\n" );
    } 

    if ( S_ISLNK( stFile.st_mode ) )
    {
        printf( "M: Symbolic Link\n" );
    }

    if ( S_ISREG( stFile.st_mode ) )
    {
        printf( "M: Regular File\n" );
    }

    if ( S_ISBLK( stFile.st_mode ) )
    {
        printf( "M: Block Device\n" );
    }

    if ( S_ISDIR( stFile.st_mode ) )
    {
        printf( "M: Directory\n" );
    }

    if ( stFile.st_mode & S_IFCHR )
    {
        printf( "M: Character Device\n" );
    }

    if ( stFile.st_mode & S_IFIFO )
    {
        printf( "M: FIFO\n" );
    }

    // Judge read, write, execute permission of owner, group, others
    if ( stFile.st_mode & S_IRUSR )
    {
        printf( "Owner Read permission\n" );
    }

    if ( stFile.st_mode & S_IWUSR )
    {
        printf( "Owner Write permission\n" );
    }

    if ( stFile.st_mode & S_IXUSR )
    {
        printf( "Owner Execute permission\n" );
    }

    if ( stFile.st_mode & S_IRGRP )
    {
        printf( "Group Read permission\n" );
    }

    if ( stFile.st_mode & S_IWGRP )
    {
        printf( "Group Write permission\n" );
    }

    if ( stFile.st_mode & S_IXGRP )
    {
        printf( "Group Execute permission\n" );
    }

    if ( stFile.st_mode & S_IROTH )
    {
        printf( "Others Read permission\n" );
    }

    if ( stFile.st_mode & S_IWOTH )
    {
        printf( "Others Write permission\n" );
    }

    if ( stFile.st_mode & S_IXOTH )
    {
        printf( "Others Execute permission\n" );
    }


    return 0;
}

#if 0
           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */(*)
               mode_t    st_mode;    /* protection */(* 权限信息)
               nlink_t   st_nlink;   /* number of hard links */(* 硬链接数)
               uid_t     st_uid;     /* user ID of owner */ (*UID 用户id)
               gid_t     st_gid;     /* group ID of owner */(*group 所在组ID)
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */(*文件的大小)
               blksize_t st_blksize; /* blocksize for file system I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               time_t    st_atime;   /* time of last access */       (*最后访问的时间)
               time_t    st_mtime;   /* time of last modification */ (*最后修改的时间)
               time_t    st_ctime;   /* time of last status change */(*最后的状态改变的时间)
           };

#endif


/*
程序功能:
    获取一个指定文件的status, 并解析一部分内容:
        inode, mode, link#, user ID of owner, user ID of group, size
    并根据Linux手册详细解析 mode 数据内容
    
涉及函数:
    stat

知识要点:
    通过 man 2 stat 和 man 7 inode, 获取详细信息, 以此解析需要的内容. 
    直播视频20220606-2.mp4中有讲解 
    <Linux程序设计>(第四版) page 88
*/